package com.example.springbootNetty.netty.server;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.example.springbootNetty.netty.annotation.SocketController;
import com.example.springbootNetty.netty.annotation.SocketMapping;
import com.example.springbootNetty.util.SpringUtil;
import org.springframework.context.annotation.DependsOn;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Author: Kevin
 * @Date: 2022/1/26 14:26
 */
@Component
@DependsOn("springUtil")
public class NettyServerContext {
    private static Map<String, Method> map = new HashMap();

    static {
        //获取所有被SocketController注解的类
        String[] beansForController = SpringUtil.getBeanNamesForAnnotation(SocketController.class);
        //将SocketMapping注解的方法的路径作为key,方法作为value存入map
        for (String bean : beansForController) {
            String keyPre = "";
            Class clazz = SpringUtil.getType(bean);
            if (clazz.isAnnotationPresent(SocketMapping.class)) {
                SocketMapping socketMapping = (SocketMapping) clazz.getAnnotation(SocketMapping.class);
                if (socketMapping.value().charAt(0) == '/') {
                    keyPre = socketMapping.value();
                } else {
                    keyPre = "/" + socketMapping.value();
                }
            }
            Method[] methods = clazz.getMethods();
            for (Method method : methods) {
                if (method.isAnnotationPresent(SocketMapping.class)) {
                    String key = keyPre;
                    SocketMapping socketMapping = method.getAnnotation(SocketMapping.class);
                    if (socketMapping.value().charAt(0) == '/') {
                        key += socketMapping.value();
                    } else {
                        key += "/" + socketMapping.value();
                    }
                    map.put(key, method);
                }
            }
        }
    }

    /**
     * 分配任务的执行器
     *
     * @param param 执行方法的参数
     */
    public String run(Object param) {
        String result = "";
        //开始调用
        JSONObject jsonObject = (JSONObject) param;
        String url = jsonObject.getString("url");
        Method method = map.get(url);
        Assert.notNull(method, "404");
        //获取方法所在类，从spring容器中取出执行方法
        Class clazz = method.getDeclaringClass();
        //给方法中的参数赋值
        List<Object> objects = new ArrayList<>();
        //参数类型
        Class[] parameterTypes = method.getParameterTypes();
        //参数名称
        DefaultParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();
        String[] parameterNames = parameterNameDiscoverer.getParameterNames(method);

        for (int i = 0; i < parameterNames.length; i++) {
            objects.add(jsonObject.getObject(parameterNames[i], parameterTypes[i]));
        }
        try {
            Object object = method.invoke(SpringUtil.getBean(clazz), objects.toArray());
            if (object instanceof String) {
                result = object.toString();
            } else {
                result = JSON.toJSONString(object);
            }
        } catch (IllegalAccessException | InvocationTargetException e) {
            e.printStackTrace();
        }
        return result;
    }
}
